package com.wcq.studentbackend.security;

import com.wcq.studentbackend.util.JwtUtil;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.SignatureException;
import io.jsonwebtoken.UnsupportedJwtException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component
public class JwtRequestFilter extends OncePerRequestFilter {

    private final UserDetailsService userDetailsService; // Spring Security 的 UserDetailsService
    private final JwtUtil jwtUtil;

    @Autowired
    public JwtRequestFilter(UserDetailsService userDetailsService, JwtUtil jwtUtil) {
        this.userDetailsService = userDetailsService;
        this.jwtUtil = jwtUtil;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException {

        final String authorizationHeader = request.getHeader("Authorization");

        String username = null;
        String jwt = null;

        // 1. 从 Authorization 头部提取 JWT (Bearer token)
        if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
            jwt = authorizationHeader.substring(7);
            try {
                username = jwtUtil.getUsernameFromToken(jwt);
            } catch (IllegalArgumentException e) {
                logger.warn("Unable to get JWT Token: " + e.getMessage());
            } catch (ExpiredJwtException e) {
                logger.warn("JWT Token has expired: " + e.getMessage());
                // 可以根据需要在这里设置特定的响应，例如 401 和特定的错误消息
                // response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                // response.getWriter().write("JWT Token has expired");
                // return; // 如果希望直接返回错误而不是继续过滤器链
            } catch (SignatureException e) {
                logger.warn("JWT Signature validation failed: " + e.getMessage());
            } catch (MalformedJwtException e) {
                logger.warn("JWT Token is malformed: " + e.getMessage());
            } catch (UnsupportedJwtException e) {
                logger.warn("JWT Token is unsupported: " + e.getMessage());
            }
        } else {
            // logger.warn("Authorization header does not begin with Bearer String or is null");
            // 对于不需要认证的路径（如登录），这是正常的，所以不一定需要警告
        }

        // 2. 如果提取到 username 并且当前 SecurityContext 中没有认证信息
        if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
            UserDetails userDetails = this.userDetailsService.loadUserByUsername(username); // username 现在应该是 "role:identifier" 格式

            // 3. 验证 token
            if (jwtUtil.validateToken(jwt, userDetails)) {
                // 如果 token 有效, 创建 Spring Security 的 Authentication 对象
                UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
                        userDetails, null, userDetails.getAuthorities());
                usernamePasswordAuthenticationToken
                        .setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                
                // 将 Authentication 对象设置到 SecurityContext 中
                SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
                logger.info("Authenticated user " + username + ", setting security context");
            } else {
                logger.warn("JWT Token validation failed for user " + username);
            }
        } else if (username != null && SecurityContextHolder.getContext().getAuthentication() != null) {
            // This case might occur if a filter earlier in the chain already authenticated.
            // logger.debug("SecurityContextHolder already contains an Authentication object for " + username);
        }
        
        chain.doFilter(request, response); // 继续执行过滤器链
    }
}